package org.sardine.beans;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

import javax.xml.parsers.ParserConfigurationException;

import org.apache.log4j.Logger;
import org.sardine.util.Assert;
import org.sardine.util.RegexUtils;
import org.w3c.dom.Document;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class DefaultXmlReader implements XmlReader{
	
	private final Logger log = Logger.getLogger(DefaultXmlReader.class);
	private XmlParser parser;
	private final XmlValidationMode validationMode;
	private ErrorHandler errorHandler = new SimpleErrorHandler(log);
	private DefaultDocumentLoader documentLoader = new DefaultDocumentLoader();
	private boolean namespaceAware = true;		//一定要为true,因为文档验证要依赖命名空间
	
	public DefaultXmlReader(){
		this.validationMode = XmlValidationMode.DTD;
	}
	
	public DefaultXmlReader(XmlValidationMode valitationMode){
		this.validationMode = valitationMode;
	}

	public void loadXmlFiles(String[] xmlLocations) {

		for(String xml : xmlLocations){
			Assert.notNull(xml, "必须提供xml文件");
			if(RegexUtils.matchXmlFileName(xml)){
				loadXmlFile(xml);
			}else{
				throw new IllegalArgumentException(xml+" 不是后缀为xml的文件");
			}
		}
		
	}

	/*
	 * 不采用此方法的原因看 XSDValidator.java
	 * 
	public void loadXmlFile(String xmlLocation) {
		Assert.notNull(xmlLocation, "必须提供xml文件");
		
		URL url = null;
		try {
			url = new URL(xmlLocation);
		} catch (MalformedURLException e) {
			e.printStackTrace();
			throw new XmlReaderException(xmlLocation+ " 格式不对");
		}
		
		InputStream is = null;
		Document document = null;
		if(url != null){
			try {
				URLConnection con = url.openConnection();
				con.setUseCaches(false);
				is = con.getInputStream();
				document = doLoadXmlFile(new InputSource(is));
				
			} catch (IOException e) {
				throw new XmlReaderException("解析 "+ xmlLocation + " 时I/O出错，可能文件不存在",e);
				
			} catch (ParserConfigurationException e) {
				throw new XmlReaderException("解析 "+ xmlLocation + " 时出错",e);
				
			} catch (SAXException e) {
				throw new XmlReaderException( xmlLocation + " 无效",e);
				
			} finally {
				try {
					is.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		
		if(document != null && register != null){
			register.registDocument(document);
		}
		
	}*/
	
	public Document loadXmlFile(String xmlLocation){
		
		Assert.notNull(xmlLocation, "必须提供xml文件");
		
		InputSource is = new InputSource(xmlLocation);
		Document document = null;
		
		try {
			
			document = doLoadXmlFile(is);
			
		} catch (ParserConfigurationException e) {
			throw new XmlReaderException("解析 "+ xmlLocation + " 时出错,原因是："+e.getMessage());
		} catch (SAXException e) {
			throw new XmlReaderException("XML文档"+ xmlLocation + " 无效,原因是："+e.getMessage());
		} catch (IOException e) {
			throw new XmlReaderException("解析 "+ xmlLocation + " 时I/O出错，可能文件不存在",e);
		}
		
		if(parser != null){
			log.info("开始解析XML文件 "+xmlLocation);
			parser.parseDocument(document);
		}
		
		return document;
	}
	
	private Document doLoadXmlFile(InputSource source) throws ParserConfigurationException, SAXException, IOException{
		
		return documentLoader.loadDocument(source, this.errorHandler, this.validationMode, this.namespaceAware);
		
	}

	public XmlParser getRegister() {
		return parser;
	}

	public XmlValidationMode getValidationMode() {
		return validationMode;
	}

	public ErrorHandler getErrorHandler() {
		return errorHandler;
	}

	public DefaultDocumentLoader getDocumentLoader() {
		return documentLoader;
	}

	public boolean isNamespaceAware() {
		return namespaceAware;
	}

	public void setParser(XmlParser parser) {
		this.parser = parser;
	}

	public void setErrorHandler(ErrorHandler errorHandler) {
		this.errorHandler = errorHandler;
	}

	public void setDocumentLoader(DefaultDocumentLoader documentLoader) {
		this.documentLoader = documentLoader;
	}

	public void setNamespaceAware(boolean namespaceAware) {
		this.namespaceAware = namespaceAware;
	}
	
	

}
